package com.wgchao.amc.service.impl;

import com.wgchao.amc.autho.AuthoInfoCenter;
import com.wgchao.amc.common.PageData;
import com.wgchao.amc.common.ResultCommon;
import com.wgchao.amc.entity.base.SysBaseAgency;
import com.wgchao.amc.mapstruct.dto.SysBaseAgencyDTO;
import com.wgchao.amc.mapstruct.mapper.SysBaseAgencyMapper;
import com.wgchao.amc.mapstruct.mapper.expand.SysBaseAgencyMapperExpand;
import com.wgchao.amc.repository.base.SysBaseAgencyRepository;
import com.wgchao.amc.service.AgencyService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @ClassName: AgencyServiceImpl
 * @author: wgchao
 * @createTime: 2019/10/14 9:31 AM
 * @Description: 机构信息管理
 */
@Service
@Transactional
public class AgencyServiceImpl implements AgencyService {
    @Autowired
    private SysBaseAgencyRepository agencyRepository;
    @Autowired
    private SysBaseAgencyMapperExpand agencyMapperExpand;

    /**
     * 新增机构
     * @param agencyDTO
     * @return
     * @throws Exception
     */
    @Override
    public ResultCommon<SysBaseAgencyDTO> save(SysBaseAgencyDTO agencyDTO, AuthoInfoCenter authoInfoCenter) throws Exception {
        SysBaseAgency pagency = null;
        if(!StringUtils.isEmpty(agencyDTO.getParCode())){
            Optional<SysBaseAgency> paragency = agencyRepository.findById(agencyDTO.getParCode());
            if(!paragency.isPresent()){
                return ResultCommon.fail("父机构不存在");
            }
            pagency = paragency.get();
            if(pagency.isDel()){
                return ResultCommon.fail("父机构已删除");
            }
            if(pagency.isCancel()){
                return ResultCommon.fail("父机构已注销");
            }
        }
        //获取机构编号
        String agencyCode = getNextAgencyCode(pagency.getAgencyCode());
        SysBaseAgency agency = agencyMapperExpand.toEntity(agencyDTO);
        agency.setAgencyCode(agencyCode);
        agency.setCancel(false);
        agency.setDel(false);
        agency.setCreateTime(new Date());
        // 创建人
        agency.setCreateUser(authoInfoCenter.getUserId());
        agency = agencyRepository.save(agency);

        agencyDTO = agencyMapperExpand.toDTO(agency);
        agencyDTO = agencyMapperExpand.getCURDUserInfo(agencyDTO);
        agencyDTO = agencyMapperExpand.getParent(agencyDTO);
        return ResultCommon.success().setData(agencyDTO);
    }

    /**
     * 根据机构编号查询机构详情
     * @param agencyCode 机构编号
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(readOnly = true)
    public ResultCommon<SysBaseAgencyDTO> search(String agencyCode) throws Exception {
        Optional<SysBaseAgency> agencyOptional = agencyRepository.findById(agencyCode);
        if(!agencyOptional.isPresent()){
            return ResultCommon.fail("机构不存在");
        }

        SysBaseAgency agency = agencyOptional.get();
        SysBaseAgencyDTO agencyDTO = agencyMapperExpand.toDTO(agency);
        agencyDTO = agencyMapperExpand.getCURDUserInfo(agencyDTO);
        agencyDTO = agencyMapperExpand.getParent(agencyDTO);
        return ResultCommon.success().setData(agencyDTO);
    }

    /**
     * 分页查询机构信息
     * @param page 页码
     * @param limit 数据条数
     * @param agencyName 机构名称
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(readOnly = true)
    public ResultCommon<PageData<SysBaseAgencyDTO>> page(int page, int limit,
                                                         String agencyName, AuthoInfoCenter authoInfoCenter) throws Exception {
        String agencyCode = authoInfoCenter.getAgencyCode();
        Specification<SysBaseAgency> specification = new Specification<SysBaseAgency>() {
            @Override
            public Predicate toPredicate(Root<SysBaseAgency> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicateList = new ArrayList<>();
                if(!StringUtils.isEmpty(agencyCode)){
                    Predicate predicate = criteriaBuilder.like(root.get("agencyCode"), agencyCode+"%");
                    predicateList.add(predicate);
                }
                if(!StringUtils.isEmpty(agencyName)){
                    Predicate predicate = criteriaBuilder.like(root.get("agencyName"), agencyName+"%");
                    predicateList.add(predicate);
                }
                Predicate predicate = criteriaBuilder.isFalse(root.get("del"));
                predicateList.add(predicate);

                Predicate[] predicates = new Predicate[predicateList.size()];
                return criteriaBuilder.and(predicateList.toArray(predicates));
            }
        };

        Pageable pageable = PageRequest.of(page-1, limit, Sort.by(Sort.Order.asc("agencyCode")));

        Page<SysBaseAgency> agencyPage = agencyRepository.findAll(specification, pageable);
        List<SysBaseAgencyDTO> agencyDTOS = agencyPage.get().map(sysBaseAgency -> {
            SysBaseAgencyDTO agencyDTO = agencyMapperExpand.toDTO(sysBaseAgency);
            agencyDTO = agencyMapperExpand.getCURDUserInfo(agencyDTO);
            agencyDTO = agencyMapperExpand.getParent(agencyDTO);
            return agencyDTO;
        }).collect(Collectors.toList());

        return ResultCommon.success().setData(new PageData<SysBaseAgencyDTO>(page, limit,
                Long.valueOf(agencyPage.getTotalElements()).intValue(), agencyDTOS));
    }

    /**
     * 更新机构信息
     * @param agencyDTO 机构信息
     * @return
     * @throws Exception
     */
    @Override
    public ResultCommon<SysBaseAgencyDTO> update(SysBaseAgencyDTO agencyDTO, AuthoInfoCenter authoInfoCenter) throws Exception {
        Optional<SysBaseAgency> agencyOptional = agencyRepository.findById(agencyDTO.getAgencyCode());
        if(!agencyOptional.isPresent()){
            return ResultCommon.fail("机构不存在");
        }
        SysBaseAgency agency = agencyOptional.get();
        if(agency.isDel()){
            return ResultCommon.fail("机构已删除");
        }
        if(!agency.getParCode().equals(agencyDTO.getParCode())){
            return ResultCommon.fail("父机构不允许在此处修改");
        }
        if(!StringUtils.isEmpty(agency.getParCode())){
            Optional<SysBaseAgency> par_agencyOptional = agencyRepository.findById(agency.getParCode());
            SysBaseAgency par_agency = par_agencyOptional.get();
            if(par_agency.isDel() || par_agency.isCancel()){
                return ResultCommon.fail("上级机构已注销或删除");
            }
        }

        SysBaseAgency baseAgency  = agencyMapperExpand.toEntity(agencyDTO);
        baseAgency.setLastUpdateTime(new Date());
        baseAgency.setLastUpdateUser(authoInfoCenter.getUserId());

        baseAgency = agencyRepository.save(baseAgency);

        agencyDTO = agencyMapperExpand.toDTO(baseAgency);
        agencyDTO = agencyMapperExpand.getCURDUserInfo(agencyDTO);
        agencyDTO = agencyMapperExpand.getParent(agencyDTO);
        return ResultCommon.success().setData(agencyDTO);
    }

    /**
     * 删除机构信息（同时删除子机构）
     * @param agencyCodes 机构编号列表
     * @return
     * @throws Exception
     */
    @Override
    public ResultCommon deletes(List<String> agencyCodes, AuthoInfoCenter authoInfoCenter) throws Exception {
        List<SysBaseAgency> delagency = new ArrayList<>();
        for(String agencyCode : agencyCodes){
            Optional<SysBaseAgency> agencyOptional = agencyRepository.findById(agencyCode);
            if(!agencyOptional.isPresent()){
                return ResultCommon.fail("机构不存在");
            }
            SysBaseAgency agency = agencyOptional.get();
            agency.setDel(true);
            agency.setDelTime(new Date());
            agency.setDelUser(authoInfoCenter.getUserId());
            delagency.add(agency);
            List<SysBaseAgency> childs = agencyRepository.findAllByAgencyCodeLike(agencyCode+"_%");
            if(childs!=null && !childs.isEmpty()){
                for(SysBaseAgency child : childs){
                    child.setDel(true);
                    child.setDelTime(new Date());
                    child.setDelUser(authoInfoCenter.getUserId());
                    delagency.add(child);
                }
            }
        }
        delagency = agencyRepository.saveAll(delagency);

        return ResultCommon.success();
    }

    /**
     * 注销机构信息（同时注销子机构）
     * @param agencyCodes 机构编号列表
     * @return
     * @throws Exception
     */
    @Override
    public ResultCommon cancels(List<String> agencyCodes, AuthoInfoCenter authoInfoCenter) throws Exception {
        List<SysBaseAgency> delagency = new ArrayList<>();
        for(String agencyCode : agencyCodes){
            Optional<SysBaseAgency> agencyOptional = agencyRepository.findById(agencyCode);
            if(!agencyOptional.isPresent()){
                return ResultCommon.fail("机构不存在");
            }
            SysBaseAgency agency = agencyOptional.get();
            if(agency.isDel()){
                return ResultCommon.fail("机构已删除");
            }
            if(!StringUtils.isEmpty(agency.getParCode())){
                Optional<SysBaseAgency> par_agencyOptional = agencyRepository.findById(agency.getParCode());
                SysBaseAgency par_agency = par_agencyOptional.get();
                if(par_agency.isDel() || par_agency.isCancel()){
                    return ResultCommon.fail("上级机构已注销或删除");
                }
            }

            if(!agency.isCancel()){
                agency.setCancel(true);
            }else{
                agency.setCancel(false);
            }
    //        agency.setCancel(true);
            agency.setLastUpdateTime(new Date());
            agency.setLastUpdateUser(authoInfoCenter.getUserId());
            delagency.add(agency);
            if(!agency.isCancel()){
                List<SysBaseAgency> childs = agencyRepository.findAllByAgencyCodeLike(agencyCode+"_%");
                if(childs!=null && !childs.isEmpty()){
                    for(SysBaseAgency child : childs){
                        child.setCancel(true);
                        child.setLastUpdateTime(new Date());
                        child.setLastUpdateUser(authoInfoCenter.getUserId());
                        delagency.add(child);
                    }
                }
            }

        }
        delagency = agencyRepository.saveAll(delagency);

        return ResultCommon.success();
    }

    /**
     * 根据机构编号查询机构以及子机构列表
     * @param agencyCode 机构编号
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(readOnly = true)
    public ResultCommon<List<SysBaseAgencyDTO>> searchChilds(String agencyCode) throws Exception {
        List<SysBaseAgency> childs = agencyRepository.findAllByAgencyCodeLikeAndDelIsFalseAndCancelIsFalse(agencyCode+"%",
                Sort.by(Sort.Order.asc("agencyCode")));
        if(childs!=null && !childs.isEmpty()){
            List<SysBaseAgencyDTO> childDTOs = childs.stream().map(sysBaseAgency -> {
                SysBaseAgencyDTO agencyDTO = agencyMapperExpand.toDTO(sysBaseAgency);
//                agencyDTO = agencyMapperExpand.getCURDUserInfo(agencyDTO);
//                agencyDTO = agencyMapperExpand.getParent(agencyDTO);
                return agencyDTO;
            }).collect(Collectors.toList());

            return ResultCommon.success().setData(childDTOs);
        }
        return ResultCommon.success();
    }

    /**
     * 根据机构编号查询机构以及子机构列表(树状结构)
     * @param agencyCode 机构编号
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(readOnly = true)
    public ResultCommon<SysBaseAgencyDTO> searchChildsTree(String agencyCode) throws Exception {
        Optional<SysBaseAgency> agencyOptional = agencyRepository.findById(agencyCode);
        if(!agencyOptional.isPresent()){
            return ResultCommon.fail("机构不存在");
        }
        SysBaseAgency agency = agencyOptional.get();

        SysBaseAgencyDTO agencyDTO = agencyMapperExpand.toDTO(agency);
//        agencyDTO = agencyMapperExpand.getCURDUserInfo(agencyDTO);
//        agencyDTO = agencyMapperExpand.getParent(agencyDTO);
        agencyDTO.setChilds(searchChildsTreeDG(agencyCode));
        return ResultCommon.success().setData(agencyDTO);
    }

    private List<SysBaseAgencyDTO> searchChildsTreeDG(String agencyCode) throws Exception{
        List<SysBaseAgency> childs = agencyRepository.findAllByAgencyCodeLikeAndDelIsFalseAndCancelIsFalse(agencyCode+"____",
                Sort.by(Sort.Order.asc("agencyCode")));
        if(childs!=null && !childs.isEmpty()){
            List<SysBaseAgencyDTO> childDTOs = agencyMapperExpand.toDTO(childs);
            for(SysBaseAgencyDTO childDTO : childDTOs){
                List<SysBaseAgencyDTO> cchilds = searchChildsTreeDG(childDTO.getAgencyCode());
                childDTO.setChilds(cchilds);
            }
            return childDTOs;
        }
        return null;
    }

    /**
     * 获取新增机构编号
     * @param parentCode 父机构编号
     * @return
     */
    public String getNextAgencyCode(String parentCode){
        String maxCode = agencyRepository.findNextChildCode(parentCode);
        if(StringUtils.isEmpty(maxCode)){
            //新增机构是第一个下级机构
            return parentCode+"0000";
        }
        else {
            //新增机构不是第一个下级机构 +1
            String index = "0000"+(Integer.valueOf(maxCode.substring(maxCode.length() - 4))+1);
            return maxCode.substring(0, maxCode.length()-4)+index.substring(index.length()-4, index.length());
        }
    }
}
